package com.hly.poitool.word;

import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.xmlbeans.XmlCursor;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDrawing;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRPrChange;

import java.io.*;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author : Jack Hao
 * @Date : 2022/4/6 17:05
 * @description : word 复制 excel 中的table
 */
public class WordAddExcelTable {


    /**
     * 把源文件中的的段落 表格 图片 合并到 目标文件中
     *
     * @param sourceSheet    源Excel文件中的sheet
     * @param targetFilePath 目标文件路径
     * @param title          匹配用的字符
     * @return
     */
    public static void addTable(Sheet sourceSheet, String targetFilePath, String title) throws Exception {
        ReentrantLock lock = new ReentrantLock();
        try {
            lock.lock();

            List<List<String>> sheetData = getSheetData(sourceSheet);

            // 把原文将中的所有数据添加到目标文件中
            setRed(sheetData, targetFilePath, title);

        } finally {
            lock.unlock();
        }
    }


    /**
     * 获取sheet 中的数据
     *
     * @param sheet
     * @return
     * @throws Exception
     */
    public static List<List<String>> getSheetData(Sheet sheet) throws Exception {
        List<List<String>> result = new ArrayList<List<String>>();
        try {

            if (sheet == null) {
                return result;
            } else {
                int rows = sheet.getPhysicalNumberOfRows();
                if (rows <= 0) {
                    return result;
                } else {
                    Row row0 = sheet.getRow(0);
                    int colunms = row0.getPhysicalNumberOfCells();
                    for (int i = 0; i < rows; i++) {
                        Row row_i = sheet.getRow(i);
                        List<String> rowData_i = new ArrayList<String>();
                        for (int j = 0; j < colunms; j++) {
                            Cell cell_i_j = row_i.getCell(j);
                            String cellVal_i_j = getCellValue(cell_i_j);
                            rowData_i.add(cellVal_i_j);
                        }
                        result.add(rowData_i);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }


    /**
     * @param cell
     * @return
     */
    public static String getCellValue(Cell cell) throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
        Object val = "";
        try {
            if (cell != null) {
                if (cell.getCellType() == CellType.NUMERIC) {
                    val = cell.getNumericCellValue();
                    if (HSSFDateUtil.isCellDateFormatted(cell)) {
                        val = DateUtil.getJavaDate((Double) val); // POI Excel date
                        val = sdf.format((Date) val);
//                        //////System.out.println("val = "+val);
                    } else {
                        if ((Double) val % 1 > 0) {
                            val = new BigDecimal(val.toString());
                        } else {
                            val = new DecimalFormat("0").format(val);
                        }
                    }
                } else if (cell.getCellType() == CellType.STRING) {
                    val = cell.getStringCellValue();
                } else if (cell.getCellType() == CellType.BOOLEAN) {
                    val = cell.getBooleanCellValue();
                } else if (DateUtil.isCellDateFormatted(cell)) {
                    val = cell.getDateCellValue();
                    if (val != null) {
                        val = sdf.format((Date) val);
                    }
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        if (val == null || val.toString().trim().equals("")) {
            val = "";
        }
        return String.valueOf(val);
    }


    /**
     * 获取 body Element 中的 段落 表格 和 图片
     *
     * @param sheetData      sheet 中的数据
     * @param targetFilePath 目标文件的路径
     * @param title          生成的word 数据
     * @return
     * @throws Exception
     */
    public static boolean setRed(List<List<String>> sheetData, String targetFilePath, String title) throws Exception {
        XWPFDocument targetDocument = new XWPFDocument();//构建模板文档对象
        FileOutputStream fileOutputStream = null;
        try {

            //获取开头的段落
            XWPFParagraph insertNewParagraph = targetDocument.createParagraph();

            XmlCursor xmlCursor = insertNewParagraph.getCTP().newCursor();//获取到段落的光标

            xmlCursor.toNextSibling();//下移光标
            insertNewParagraph = targetDocument.insertNewParagraph(xmlCursor);//在当前光标处插入新的段落
            xmlCursor = insertNewParagraph.getCTP().newCursor();

            //插入标题
            XWPFRun newRun = insertNewParagraph.createRun();
            newRun.setText(title);

            xmlCursor = insertNewParagraph.getCTP().newCursor();
            xmlCursor.toNextSibling();//下移光标

            xmlCursor = copyTable(targetDocument, xmlCursor, sheetData);




            fileOutputStream = new FileOutputStream(targetFilePath);
            targetDocument.write(fileOutputStream);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (targetDocument != null) {
                try {
                    targetDocument.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return true;
    }


    /**
     * 复制 源文件中的段落到目标文件 段落有两种 一种是文字 另一种是图片 需要进行判断
     *
     * @param sourceParagraph 源文件的段落
     * @param targetParagraph 目标文件的段落
     * @param pictures        图片集合
     * @param pictureIndex    获取到图标的下角标
     * @return
     * @throws IOException
     * @throws InvalidFormatException
     */
    public static void copyParagraph(XWPFParagraph sourceParagraph, XWPFParagraph targetParagraph, List<XWPFPictureData> pictures, int pictureIndex) throws IOException, InvalidFormatException {
        List<XWPFRun> runs = sourceParagraph.getRuns();//获取run对象

        //复制源段落样式到新的段落
        ParagraphAlignment alignment = sourceParagraph.getAlignment();
        if (alignment != null) {
            targetParagraph.setAlignment(alignment);
        }

        for (int k = 0; k < runs.size(); k++) {

            XWPFRun oldRun = runs.get(k);
            CTR oldCtr = oldRun.getCTR();
            List<CTDrawing> drawingList = oldCtr.getDrawingList();
            CTRPr oldRPr = oldCtr.getRPr();
            if (oldRPr != null) {
                CTRPrChange oldRPrChange = oldRPr.getRPrChange();//run标签里也有rprchange标签也需要像上面一样设置
                if (oldRPrChange != null) {
                    oldRPr.unsetRPrChange();
                }
            }
            XWPFRun newRun = targetParagraph.createRun();
            if (oldRPr != null) {
                newRun.getCTR().setRPr(oldRPr);
            }

            if (drawingList.size() > 0) { //判断是图片 复制图片

                CTDrawing drawing = drawingList.get(0);
                List<CTInline> inlineList = drawing.getInlineList();
                CTInline ctInline = inlineList.get(0);
                CTPositiveSize2D extent = ctInline.getExtent();
                long cx = extent.getCx();
                long cy = extent.getCy();

                //图片在word中的宽
                int w = new Long(cx).intValue();
                //图片在word中的高
                int y = new Long(cy).intValue();

                XWPFPictureData xwpfPictureData = pictures.get(pictureIndex);
                pictureIndex++;
                byte[] data = xwpfPictureData.getData();

                String picName = "drw-" + UUID.randomUUID().toString();
                newRun.addPicture(new ByteArrayInputStream(data), XWPFDocument.PICTURE_TYPE_PNG, picName, w, y);

            } else {//不是图片 复制文字
                String text = oldRun.text();
                newRun.setText(text);
            }
            targetParagraph.addRun(newRun);
        }
    }


    /**
     * 复制 源文件中的 table 到 目标文件
     *
     * @param targetDocument 目标文件 document 对象
     * @param xmlCursor      目标文件的光标
     * @param sheetData      sheet 中的数据
     * @return 返回光标
     */
    public static XmlCursor copyTable(XWPFDocument targetDocument, XmlCursor xmlCursor, List<List<String>> sheetData) {

        //目标文件 中插入一个 table
        XWPFTable insertNewTable = targetDocument.insertNewTbl(xmlCursor);


        //获取源文件的表的行数
        int size = sheetData.size();

        for (int i = 0; i < size; i++) {

            //源文件的 i 行 数据
            List<String> rowList_i = sheetData.get(i);

            int cellSize = rowList_i.size();


            //目标文件  table 第一行 不需要新建
            XWPFTableRow createRow_i = null;
            if (i == 0) {
                createRow_i = insertNewTable.getRow(0);
            } else {//目标文件  table 不是第一行 需要新建
                createRow_i = insertNewTable.createRow();
            }


            //便利源文件的所有单元格
            for (int k = 0; k < cellSize; k++) {
                //第 k 个 单元格
                String cell_k_val = rowList_i.get(k);
                XWPFTableCell createCell_k = null;
                if (i == 0) {//第一行的单元格
                    if (k == 0) {//第一行第一个单元格 不需要新建
                        createCell_k = createRow_i.getCell(0);
                    } else {//第一行 不是第一个单元格 需要新建
                        createCell_k = createRow_i.createCell();
                    }
                } else {//不是第一行的单元格不需要新建
                    createCell_k = createRow_i.getCell(k);
                }

                //移除单元格内默认的段落
                createCell_k.removeParagraph(0);

                createCell_k.setText(cell_k_val);

            }
        }
        xmlCursor = insertNewTable.getCTTbl().newCursor();
        return xmlCursor;
    }



    public static void main(String[] args) {
        //合并文件
        InputStream is = null;
        Workbook wb = null;
        try {

            String sourceExcelPath = "D:\\svncode\\GW_2021x\\新建文件夹\\测试示例数据\\正常值范围\\XAST-T004正常值范围.xlsx";


            is = new FileInputStream(sourceExcelPath);
            wb = WorkbookFactory.create(is);
            //int sheets = wb.getNumberOfSheets();
            Sheet sheet0 = wb.getSheetAt(0);
            addTable(sheet0, "D:\\svncode\\GW_2021x\\新建文件夹\\测试示例数据\\正常值范围\\4.3 测控分系统.docx", "4.3 测控分系统");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (wb != null) {
                wb = null;
            }
        }

    }


}
